﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace StableDiffusionTools.Controls
{
    public class LetterBoxImageControl : ImageControl
    {
        bool middleDown = false;
        bool loadingImage = false;
        PointF mouseLocationDelta;
        bool resetLetterboxBounds = false;

        bool letterboxEnabled = false;
        public bool LetterboxEnabled
        {
            get => letterboxEnabled;
            set
            {
                if (value == letterboxEnabled) return;

                if (!value)
                    middleDown = false;

                letterboxEnabled = value;
                Invalidate();
            }
        }

        RectangleF letterboxBounds = default(RectangleF);
        public RectangleF LetterboxBounds
        {
            get => letterboxBounds;
            set
            {
                if (value == letterboxBounds) return;

                letterboxBounds = value;
                Invalidate();
            }
        }


        private Color letterboxColor = Color.FromArgb(120, Color.Black);
        public Color LetterboxColor
        {
            get => letterboxColor;
            set
            {
                if (letterboxColor == value) return;

                letterboxColor = value;
                if (letterboxEnabled)
                    Invalidate();
            }
        }

        public void SetLetterBoxBounds(RectangleF newBounds, bool boundCheck = true)
        {
            if(boundCheck)
            {
                if (newBounds.Width > ImageSize.Width)
                {
                    newBounds.X = (ImageSize.Width - newBounds.Width) / 2;
                }
                else
                {
                    if (newBounds.X <= 0)
                    {
                        newBounds.X = 0;
                    }
                    else if (newBounds.Right > ImageSize.Width)
                    {
                        newBounds.X = ImageSize.Width - newBounds.Width;
                    }
                }

                if (newBounds.Height > ImageSize.Height)
                {
                    newBounds.Y = (ImageSize.Height - newBounds.Height) / 2;
                }
                else
                {
                    if (newBounds.Y <= 0)
                    {
                        newBounds.Y = 0;
                    }
                    else if(newBounds.Bottom > ImageSize.Height)
                    {
                        newBounds.Y = ImageSize.Height - newBounds.Height;
                    }
                }
            }

            LetterboxBounds = newBounds;
        }

        public void CenterLetterBoxBounds()
        {
            LetterboxBounds = new RectangleF((ImageSize.Width - LetterboxBounds.Width) / 2, (ImageSize.Height - LetterboxBounds.Height) / 2, LetterboxBounds.Width, letterboxBounds.Height);;
        }

        public void SetImage(Bitmap value, bool forceRefresh = false, bool resetLetterboxBounds = false)
        {
            loadingImage = true;
            this.resetLetterboxBounds = resetLetterboxBounds;
            base.SetImage(value, forceRefresh);
            this.resetLetterboxBounds = false;
            loadingImage = false;
        }

        protected override void UpdateImageOrigin(PointF deltaP = default(PointF), bool forceInvalidate = false)
        {
            base.UpdateImageOrigin(deltaP, forceInvalidate);
            if (loadingImage && !middleDown && resetLetterboxBounds)
            {
                CenterLetterBoxBounds();
                this.resetLetterboxBounds = false;
            }
        }

        protected override void DrawOverlay(PaintEventArgs e)
        {
            if (letterboxEnabled)
            {
                RectangleF letterbox = new RectangleF((float)(DestinationRect.X + ((letterboxBounds.X - SourceRect.X) * Zoom)), (float)(DestinationRect.Y + ((letterboxBounds.Y - SourceRect.Y) * Zoom)), (float)(letterboxBounds.Width * Zoom), (float)(letterboxBounds.Height * Zoom));
                using(var brush = new SolidBrush(letterboxColor))
                using (GraphicsPath path = new GraphicsPath())
                {
                    path.AddRectangle(ClientRectangle);
                    path.AddRectangle(Rectangle.Truncate(letterbox));
                    e.Graphics.FillPath(brush, path);
                }
            }
        }

        protected override void OnMouseMove(MouseEventArgs e)
        {
            base.OnMouseMove(e);
            if (letterboxEnabled && middleDown && !SourceRect.IsEmpty)
            {
                PointF delta = new PointF(e.Location.X - mouseLocationDelta.X, e.Location.Y - mouseLocationDelta.Y);
                mouseLocationDelta = e.Location;
                double zoom = ModifierKeys.HasFlag(Keys.Control) ? 1.0 : Zoom;
                RectangleF testBounds = new RectangleF((float)(letterboxBounds.X + (delta.X / zoom)), (float)(letterboxBounds.Y + (delta.Y / zoom)), (float)(letterboxBounds.Width), (float)(letterboxBounds.Height));
                
                LetterboxBounds = testBounds;
            }
        }

        protected override void OnMouseDown(MouseEventArgs e)
        {
            base.OnMouseDown(e);
            if (letterboxEnabled && e.Button == MouseButtons.Middle)
            {
                mouseLocationDelta = e.Location;
                middleDown = true;
                Focus();
            }
        }

        protected override void OnMouseUp(MouseEventArgs e)
        {
            base.OnMouseUp(e);
            if (letterboxEnabled && e.Button == MouseButtons.Middle)
            {
                middleDown = false;
                SetLetterBoxBounds(LetterboxBounds, true);
            }
        }
        //protected override void OnMouseWheel(MouseEventArgs e)
        //{
        //    if (ModifierKeys.HasFlag(Keys.Control))
        //    {

        //    }
        //    else
        //    {
        //        base.OnMouseWheel(e);
        //    }


        //    int delta = e.Delta / 120;
        //    int deltaAbs = Math.Abs(delta);
        //    float newZoom = zoom;
        //    float zoomFactor = delta < 0 ? 0.9f : 1.1f;

        //    for (int i = 0; i < deltaAbs; i++)
        //        newZoom = MathUtil.Clamp(newZoom * zoomFactor, 0.1f, 10.0f);

        //    if (newZoom > 0.9f && newZoom < 1.1f)
        //        newZoom = 1.0f;

        //    Zoom = (float)Math.Round(newZoom, 2);
        //}
    }
}
